package com.um.jdy.app.charge.scheduled;

import cn.hutool.core.util.StrUtil;
import com.um.jdy.app.charge.manager.EVOrderManager;
import com.um.jdy.common.charge.entity.po.Order;
import com.um.jdy.common.charge.enums.OrderEnum;
import com.um.jdy.common.charge.enums.OrderStopReason;
import com.um.jdy.common.charge.service.OrderService;
import com.um.jdy.common.commons.properties.HshChargingProperties;
import com.um.jdy.rpc.factory.ServiceFactory;
import com.um.springboot.starter.utils.StringUtil;
import com.um.springcloud.dubbo.cluster.DeviceKey;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 甘天伟
 * @since 2022/4/23
 * 版权所有 广州优匠科技有限公司
 */
@Slf4j
@Component
public class EVOrderTask {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    HshChargingProperties hshChargingProperties;

    @Autowired
    OrderService orderService;

    @Autowired
    EVOrderManager evOrderManager;

    @Autowired
    ServiceFactory serviceFactory;

    private static final String DEVICE_ERROR_PREFIX = "ORDER_";


    /**
     * 停止超时未启动订单定时任务
     */
    @Async
    @Scheduled(fixedRate = 180000, initialDelay = 30000)
    public void stopTimeoutUnstartedOrder() {
        log.info("【执行停止超时未启动订单定时任务】");
        List<Order> orderList = orderService.getListBySqlName("get_timeout_not_started_ev_order_list", new Object[0]);
        for (Order order : orderList) {
            try {
                evOrderManager.stopCharge(order.getOrderNo(), OrderStopReason.EV.SYS_END.name(), true);
                log.info("订单[{}]超时未启动，平台自动停止", order.getOrderNo());
            } catch (Exception ex) {
                log.error(StrUtil.format("停止超时未启动订单[{}]出错", order.getOrderNo()), ex);
            }
        }
        log.info("处理完成{}个订单", orderList.size());
    }

    /**
     * 停止设备异常订单定时任务
     */
    @Async
    @Scheduled(fixedRate = 180000, initialDelay = 60000)
    public void stopDeviceErrorOrder() {
        log.info("【执行停止设备异常订单定时任务】");
        List<Order> orderList = orderService.getListBySqlName("get_device_stop_charging_ev_order_list", new Object[0]);
        for (Order order : orderList) {
            try {

                int errorCount = StringUtil.toInt(redisTemplate.opsForValue().get(DEVICE_ERROR_PREFIX+order.getOrderNo()));

                //2次才会结束订单，避免充电桩误报
                if(errorCount >= hshChargingProperties.getDeviceErrorStopCount()){
                    evOrderManager.stopCharge(order.getOrderNo(), OrderStopReason.EV.SYS_END.name(), true);
                    log.info("订单[{}]设备状态异常，平台自动停止", order.getOrderNo());
                }else{
                    errorCount ++;
                    redisTemplate.opsForValue().set(DEVICE_ERROR_PREFIX+order.getOrderNo(),errorCount,10, TimeUnit.MINUTES);
                    log.info("订单[{}]设备状态异常，平台记录查询次数到达{}次会自动结束，当前次数为：{}", order.getOrderNo(),hshChargingProperties.getDeviceErrorStopCount(),errorCount);
                }
            } catch (Exception ex) {
                log.error(StrUtil.format("停止设备异常订单[{}]出错", order.getOrderNo()), ex);
            }
        }
    }

    /**
     * 充电桩离线且充电超出12小时，平台结束订单
     */
    @Async
    @Scheduled(fixedRate = 180000, initialDelay = 90000)
    public void autoStopOfflineLargeTimeOrders() {
        log.info("【执行停止充电桩离线且充电超出12小时订单定时任务】");
        List<Order> orderList = orderService.getListBySqlName("get_device_offline_charging_large_time_list", new Object[0]);
        for (Order order : orderList) {
            try {
                evOrderManager.stopCharge(order.getOrderNo(), OrderStopReason.EV.SYS_END.name(), true);
                log.info("订单[{}]充电桩离线且充电超出12小时，平台自动停止", order.getOrderNo());
            } catch (Exception ex) {
                log.error(StrUtil.format("停止超充电桩离线且充电超出12小时订单[{}]出错", order.getOrderNo()), ex);
            }
        }
        log.info("处理完成{}个订单", orderList.size());
    }

    /**
     * 订单超时未启动处理任务（一次性定时任务）
     *
     * @param orderNo
     */
    @Async
    public void timeoutNotStartedTask(String orderNo) {
        Order order = orderService.getRow(new String[]{"order_no", "status"},
                new Object[]{orderNo, OrderEnum.Status.NotStarted.name()});
        if (null == order) {
            return;
        }

        log.info("自动取消未启动订单{}", orderNo);
        try {
            evOrderManager.stopCharge(orderNo, OrderStopReason.EV.PLATFORM_CANCEL.name(), true);
        } catch (Exception ex) {
            log.error(StrUtil.format("自动取消未启动订单{}出错", orderNo), ex);
        }
    }

    /**
     * 下发给桩结束充电
     * @param imei 桩号
     * @param port 枪号
     */
    @Async
    public void pushDeviceStopCharge(String protocol,String imei,Integer port) {
        try {
            serviceFactory.getRpcEVDeviceService(protocol).stopCharge(new DeviceKey(imei),port);
        }catch (Exception ex){
            log.error("异常订单下发给桩结束充电:{}-{}:{}",imei,port,ex.getMessage());
        }
    }

}
